﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Linq.Expressions;
using System.Reflection;
using System.Text;

namespace Defero.Core
{
    /// <summary>
    /// Representa a un objeto anemico de dominio.
    /// </summary>
    public abstract class Entity : INotifyPropertyChanged, INotifyPropertyChanging, IDisposable
    {
        /// <summary>
        /// Constructor default.
        /// </summary>
        public Entity() 
        {
            hasPropertyTracking = false;
        }
        /// <summary>
        /// Ocurre cuando una propiedad ha cambiado de valor.
        /// </summary>
        public event PropertyChangedEventHandler PropertyChanged;
        /// <summary>
        /// Ocurre cuando una propiedad esta a punto de cambiar de valor
        /// </summary>
        public event PropertyChangingEventHandler PropertyChanging;
        /// <summary>
        /// Expone el evento a las clases derivadas.
        /// </summary>
        /// <param name="e">Argumentos del evento.</param>
        protected void OnPropertyChange<TResult>(Expression<Func<Entity, TResult>> propertySelector) 
        {
            if (!hasPropertyTracking) return;
            if (PropertyChanged == null) return;
            var memberExpression = propertySelector.Body as MemberExpression;
            if (memberExpression == null) return;

            PropertyChanged(this, new PropertyChangedEventArgs(memberExpression.Member.Name));            
        }
        /// <summary>
        /// Expone el evento a las clases derivadas.
        /// </summary>
        /// <param name="e">Argumentos del evento.</param>
        protected void OnPropertyChanging<TResult>(Expression<Func<Entity, TResult>> propertySelector) 
        {
            if (!hasPropertyTracking) return;
            if (PropertyChanging == null) return;
            var memberExpression = propertySelector.Body as MemberExpression;
            if (memberExpression == null) return;

            PropertyChanging(this, new PropertyChangingEventArgs(memberExpression.Member.Name));            
        }
        /// <summary>
        /// Determina si hay control de cambios para propiedades.
        /// Default = False
        /// </summary>
        bool hasPropertyTracking;
        /// <summary>
        /// Activa el control de cambios para propiedades;
        /// </summary>
        protected void EnablePropertyTracking() 
        {
            hasPropertyTracking = true;
        }
        /// <summary>
        /// Implementación de interfaz IDisposable.
        /// </summary>
        public void Dispose()
        {
            if(PropertyChanged != null) PropertyChanged = null;
            if(PropertyChanging != null) PropertyChanging = null;
        }
    }
}
